﻿using System;
using System.Data.SqlTypes;
using System.Text;
using Microsoft.SqlServer.Server;
using StockholmsStad.Database.Procedures;
using StockholmsStad.Database.Procedures.Enum;

/// <summary>
/// 
/// </summary>
public class StoredProcedures
{
    /// <summary>
    /// Skickar iväg ett email vid registrering
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="person1FullName"></param>
    /// <param name="userName"></param>
    /// <param name="password"></param>
    [SqlProcedure]
    public static void SendRegistrationMail(string recipient, string person1FullName,
                                            string userName, string password)
    {
        var arguments = new[] {person1FullName, userName, password};
        var procedure = new ParvisStoredProcedure(EmailTemplate.RegistrationMail, recipient,
                                                        arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email vid registrering
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="userName"></param>
    /// <param name="password"></param>
    [SqlProcedure]
    public static void SendRegistrationInParvisMail(string recipient, string userName, string password)
    {
        var arguments = new[] { userName, password };
        var procedure = new ParvisStoredProcedure(EmailTemplate.RegistrationParvisAdministrationSystemMail,
            recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med lösenordspåminnelse
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="person1FullName"></param>
    /// <param name="userName"></param>
    /// <param name="password"></param>
    [SqlProcedure]
    public static void SendForgottenPasswordMail(string recipient, string person1FullName,
                                                 string userName, string password)
    {
        var arguments = new[] {person1FullName, userName, password};
        var procedure = new ParvisStoredProcedure(EmailTemplate.ForgottenPasswordMail, recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med lösenordspåminnelse
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="lastDateForImpedimentDoc">Sista dagen för inskickning av hindersprövning</param>
    [SqlProcedure]
    public static void SendRemindCoupleOfImpedimentDocMail(string recipient, DateTime lastDateForImpedimentDoc)
    {
        var arguments = new object[] {lastDateForImpedimentDoc};
        var procedure = new ParvisStoredProcedure(EmailTemplate.RemindCoupleOfImpedimentDoc, recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med bokningsinformation om bokningen i stadshuset.
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="bookingDateTime">Bokningsdatum</param>
    /// <param name="preferredDate1">Önskat datum 1</param>
    /// <param name="preferredDate2">Önskat datum 2, kan vara null</param>
    /// <param name="earliestApplyDateForImpedimentDoc">Tidigaste datum för ansökan om hindersprövning</param>
    [SqlProcedure]
    public static void SendOrdinaryBookingMail(string recipient, DateTime bookingDateTime,
                                               DateTime preferredDate1, SqlDateTime preferredDate2,
                                               DateTime earliestApplyDateForImpedimentDoc)
    {
        DateTime? preferredDate2_internal = GetDateTimeFromSqlType(preferredDate2);
        var arguments = new[]
                                 {
                                     bookingDateTime,
                                     preferredDate1,
                                     ((object) preferredDate2_internal) ?? "",
                                     earliestApplyDateForImpedimentDoc
                                 };
        var procedure = new ParvisStoredProcedure(EmailTemplate.PreliminaryOrdinaryBookingMail, recipient, arguments);
        procedure.ExecuteProcedure();
    }



    /// <summary>
    /// Skickar iväg ett email med bokningsinformation om den individuella bokningen
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="bookingDateTime">Bokningsdatum</param>
    /// <param name="earliestApplyDateForImpedimentDoc">Tidigaste datum för ansökan om hindersprövning</param>
    [SqlProcedure]
    public static void SendIndividualBookingMail(string recipient, DateTime bookingDateTime, DateTime earliestApplyDateForImpedimentDoc)
    {
        var arguments = new object[]
                            {
                                bookingDateTime,
                                earliestApplyDateForImpedimentDoc
                            };
        var procedure = new ParvisStoredProcedure(EmailTemplate.PreliminaryIndividualBookingMail, recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med bokningsinformation om den individuella bokningen
    /// </summary>
    /// <param name="recipient">Mottagarens mailadress.</param>
    /// <param name="bookingDateTime">Bokningsdatum för vigseln. </param>
    /// <param name="person1">Namn på den ena personen i paret. </param>
    /// <param name="person2">Namn på den andra personen i paret. </param>
    [SqlProcedure]
    public static void SendIndividualBookingToMinisterMail(string recipient, DateTime bookingDateTime, string person1, string person2)
    {
        var arguments = new object[]
                            {
                                person1,
                                person2,
                                bookingDateTime,
                            };

        var procedure = new ParvisStoredProcedure(EmailTemplate.PreliminaryBookingMinisterMail, recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med bokningsinformation
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="preferredDate1">Önskat datum 1</param>
    /// <param name="preferredDate2">Önskat datum 2, kan vara null</param>
    [SqlProcedure]
    public static void SendPreferredOrdinaryBookingMail(string recipient, DateTime preferredDate1, SqlDateTime preferredDate2)
    {
        DateTime? preferredDate2_internal = GetDateTimeFromSqlType(preferredDate2);
        var arguments = new object[]
                                 {
                                     preferredDate1,
                                     ((object) preferredDate2_internal) ?? "",
                                 };
        var procedure = new ParvisStoredProcedure(EmailTemplate.PreferredDateBookingMail, recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med bokningsinformation
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="preferredDate">Önskat datum</param>
    [SqlProcedure]
    public static void SendOnePreferredOrdinaryBookingMail(string recipient, DateTime preferredDate)
    {
        var arguments = new object[]
                                 {
                                     preferredDate
                                 };
        var procedure = new ParvisStoredProcedure(EmailTemplate.OnePreferredDateBookingMail, recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email för bekräftelse att HP inkommit
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="date"></param>
    [SqlProcedure]
    public static void SendConfirmedBookingMail(string recipient, DateTime date)
    {
        var arguments = new object[] { date, 
                                       date.Minute == 0 && date.Hour == 0 ? 
                                       "" : 
                                       date.ToString(" klockan HH:mm")};
        var procedure = new ParvisStoredProcedure(EmailTemplate.ConfimedBookingMail, recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med avbokningsinformation
    /// </summary>
    /// <param name="recipient"></param>
    [SqlProcedure]
    public static void SendRemoveBookingMail(string recipient)
    {
        var arguments = new object[] {};
        var procedure = new ParvisStoredProcedure(EmailTemplate.PreliminaryRemoveBookingMail, recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med avbokningsinformation då hindersprövning inte har inkommit i tid
    /// </summary>
    /// <param name="recipient"></param>
    [SqlProcedure]
    public static void SendRemoveBookingImpedimentDocMail(string recipient)
    {
        var arguments = new object[] {};
        var procedure = new ParvisStoredProcedure(EmailTemplate.PreliminaryRemoveBookingMailImpedimentDoc,
                                                        recipient,
                                                        arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med bokningsinformation
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="bookingDateTime">Bokningsdatum</param>
    /// <param name="earliestApplyDateForSkattteverket">Tidigaste datum för ansökan om hindersprövning</param>
    [SqlProcedure]
    public static void SendOrdinaryBookingWithoutPreferredDateMail(string recipient, DateTime bookingDateTime, 
        DateTime earliestApplyDateForSkattteverket)
    {
        var arguments = new object[] {bookingDateTime, 
                                      earliestApplyDateForSkattteverket
                                    };
        var procedure = new ParvisStoredProcedure(EmailTemplate.PreliminaryBookingMailWithoutPreferrence,
                                                        recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// Skickar iväg ett email med bokningsinformation
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="bookingDateTime">Datum och tid för avbokning</param>
    /// <param name="applicationChangeDateOrdinaryBookingDays">Minsta antal dagar för webbbokning</param>
    [SqlProcedure]
    public static void SendPreferredDateNotificationMail(string recipient, DateTime bookingDateTime, int applicationChangeDateOrdinaryBookingDays)
    {
        var arguments = new object[] { bookingDateTime };
        bool manualBooking = DateTime.Now.AddDays(applicationChangeDateOrdinaryBookingDays).CompareTo(bookingDateTime) > 0;
        var procedure = new ParvisStoredProcedure(manualBooking ? EmailTemplate.NotifyCoupleWithPreferredDateManualBooking : EmailTemplate.NotifyCoupleWithPreferredDate,
                                                        recipient, arguments);
        procedure.ExecuteProcedure();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="bookingDateTime"></param>
    /// <param name="person1FirstNames"></param>
    /// <param name="person1LastName"></param>
    /// <param name="person2FirstNames"></param>
    /// <param name="person2LastName"></param>
    [SqlProcedure]
    public static void SendRemoveIndividualBookingToMinisterMail(string recipient, DateTime bookingDateTime,
        string person1FirstNames, string person1LastName, string person2FirstNames, string person2LastName)
    {
        var arguments = new object[] { person1FirstNames, person1LastName, person2FirstNames, person2LastName, bookingDateTime };
        var procedure = new ParvisStoredProcedure(EmailTemplate.PreliminaryRemoveIndividualBookingMailToMinister, recipient, arguments);
        procedure.ExecuteProcedure();        
    }

    /// <summary>
    /// Ett påminnelsemail till förrättare om tjänstgöring i stadshuset ett visst datum. 
    /// </summary>
    /// <param name="recipient">Mottagaren av mailet.</param>
    /// <param name="serviceDate">Det datum då tjänstgöringen gäller.</param>
    /// <param name="coupleRegister">En förteckning över de par som ska vigas detta datum. </param>
    [SqlProcedure]
    public static void SendMinisterServiceReminderMail(string recipient, DateTime serviceDate, string coupleRegister)
    {
        var formattedRegister = FormatCoupleRegister(coupleRegister);
        var arguments = new object[] { serviceDate, formattedRegister};
        var procedure = new ParvisStoredProcedure(EmailTemplate.MinisterServiceReminderMail, recipient, arguments);
        procedure.ExecuteProcedure();                
    }

    /// <summary>
    /// Skickar iväg ett email till förättare att påminnelse om saknat HP skickats till paret
    /// </summary>
    /// <param name="recipient"></param>
    /// <param name="individualBookingDate">Datum för ceremoni</param>
    /// <param name="person1">Namn på den ena personen i paret. </param>
    /// <param name="person2">Namn på den andra personen i paret. </param>
    [SqlProcedure]
    public static void NotifyMinisterServiceAboutRemindMail(string recipient, DateTime individualBookingDate, string person1, string person2)
    {
        var arguments = new object[] { individualBookingDate, person1, person2 };
        var procedure = new ParvisStoredProcedure(EmailTemplate.NotifyMinisterServiceAboutRemindMail, recipient, arguments);
        procedure.ExecuteProcedure();
    }
    /// <summary>
    /// Konverterar SQLtyp till vanlig DateTime.
    /// SqlDateTime måste användas om värdet kan vara null, men den typen fungerar inte bra ihop med string.format
    /// </summary>
    /// <param name="preferredDate2"></param>
    /// <returns></returns>
    private static DateTime? GetDateTimeFromSqlType(SqlDateTime preferredDate2)
    {
        return preferredDate2.IsNull ? (DateTime?) null : new DateTime(preferredDate2.Value.Ticks);
    }

    private static string FormatCoupleRegister(string register)
    {
        var coupleSeparator = new[] { ";" };
        var partSeparator = new[] { "," };

        var sbCouple = new StringBuilder();
        foreach (var couplepart in register.Split(coupleSeparator, StringSplitOptions.RemoveEmptyEntries))
        {
            // Strängen består alltid av 3 delar, tid, person1, person2
            var couplePart = couplepart.Split(partSeparator, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < couplePart.Length; i++)
            {
                if (i == 0)
                {
                    DateTime date;
                    if (DateTime.TryParse(couplePart[i], out date))
                        sbCouple.AppendFormat(" {0} ", date.ToString("HH:mm"));
                }
                else if (i == 1)
                {
                    // Sätt in bindestreck efter person1
                    sbCouple.AppendFormat("{0} - ", couplePart[i]);
                }
                else
                {
                    sbCouple.AppendFormat("{0}", couplePart[i]);
                }
            }

            sbCouple.AppendFormat("\n");
        }

        return sbCouple.ToString();
    }
}